#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "my_nvs.h"

static uint64_t peer_addr = 0;

static bool _nvs_open(nvs_handle_t *handle)
{
    esp_err_t err;
    // 打开
    printf("\n");
    printf("Opening Non-Volatile Storage (NVS) handle... ");
    err = nvs_open("storage", NVS_READWRITE, handle);
    if (err != ESP_OK) {
        printf("Error (%s) opening NVS handle!\n", esp_err_to_name(err));
        return false;
    } else {
        printf("Done\n");
    }
    return true;
}

// 获取蓝牙MAC
void my_nvs_read_mac(esp_bd_addr_t addr)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // 打开
    if(_nvs_open(&my_handle))
    {
        // 读取
        printf("Reading bt mac from NVS ... ");
        err = nvs_get_u64(my_handle, "bt_mac", &peer_addr);
        switch (err) {
            case ESP_OK:
                printf("Done\n");
                // 拷贝
                memcpy(addr, &peer_addr, sizeof(esp_bd_addr_t));
                break;
            case ESP_ERR_NVS_NOT_FOUND:
                printf("The value is not initialized yet!\n");
                break;
            default :
                printf("Error (%s) reading!\n", esp_err_to_name(err));
        }
        // 关闭
        nvs_close(my_handle);
    }
}

// 储存蓝牙MAC
void my_nvs_write_mac(esp_bd_addr_t addr)
{
    nvs_handle_t my_handle;
    esp_err_t err;
    // 检查是否重复写入
    if(!memcmp(addr, &peer_addr, sizeof(esp_bd_addr_t))) return;
    memcpy(&peer_addr, addr, sizeof(esp_bd_addr_t));
    // 打开
    if(_nvs_open(&my_handle))
    {
        // 写入
        printf("Updating bt mac in NVS ... ");
        err = nvs_set_u64(my_handle, "bt_mac", peer_addr);
        printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
        // 提交写入
        // After setting any values, nvs_commit() must be called to ensure changes are written
        // to flash storage. Implementations may write to storage at other times,
        // but this is not guaranteed.
        printf("Committing updates in NVS ... ");
        err = nvs_commit(my_handle);
        printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
        // 关闭
        nvs_close(my_handle);
    }
}

// 初始化 Non-Volatile Storage (NVS)
void my_nvs_init(void)
{
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK( err );
}
